package com.jeaven.rtda;

public class OperandStack {
    private Stack<Slot> slots;

    public OperandStack(int maxStackSize) {
        slots = new Stack<>(maxStackSize);
    }

    public String debug() {
        StringBuffer sb = new StringBuffer("OperandSrack: [ ");
        for(Slot slot : slots) {
            sb.append(slot.toString());
        }
        sb.append(" ]");
        return sb.toString();
    }

    public void pushInt(Integer val, int type) {
        this.slots.push(new Slot(val, type));
    }

    public Integer popInt() {
        return this.slots.pop().num;
    }

    public void pushFloat(Float val, int type) {
        int tmp = Float.floatToIntBits(val);
        this.slots.push(new Slot(tmp, type));
    }

    public Float popFloat() {
        Integer tmp = this.slots.pop().num;
        return Float.intBitsToFloat(tmp);
    }

    public void pushDouble(Double val) {
        long tmp = Double.doubleToLongBits(val);
        this.pushLong(tmp);
    }

    public Double popDouble() {
        Long tmp = this.popLong();
        return Double.longBitsToDouble(tmp);
    }

    public void pushRef(Object val) {
        this.slots.push(new Slot(val));
    }

    public Object popRef() {
        return this.slots.pop().ref;
    }

    public void pushLong(Long val) {
        int low = (int) (val & 0x00000000ffffffffL);
        int high = (int) (val >> 32);
        Slot lowSlot = new Slot(low, Slot.LONG_LOW);
        Slot highSlot = new Slot(high, Slot.LONG_HIGH);
        slots.push(lowSlot);
        slots.push(highSlot);
    }

    public Long popLong() {
        int high = slots.pop().num;
        int low = slots.pop().num;
        Long lhigh = (high & 0x00000000ffffffffL) << 32;
        Long llow = (low & 0x00000000ffffffffL);
        return lhigh | llow;
    }
}
